package com.haifeng.jupiter.auth.endpoint.controller;

import cn.hutool.core.util.ObjectUtil;
import cn.hutool.http.HttpStatus;
import com.github.xiaoymin.knife4j.annotations.ApiOperationSupport;
import com.github.xiaoymin.knife4j.annotations.ApiSort;
import com.haifeng.jupiter.auth.param.LoginParam;
import com.haifeng.jupiter.auth.param.RefreshTokenParam;
import com.haifeng.jupiter.common.core.base.Rest;
import com.haifeng.jupiter.common.core.exception.BusinessException;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.http.client.support.BasicAuthenticationInterceptor;
import org.springframework.security.oauth2.common.OAuth2AccessToken;
import org.springframework.util.LinkedMultiValueMap;
import org.springframework.util.MimeTypeUtils;
import org.springframework.util.MultiValueMap;
import org.springframework.validation.BindingResult;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.client.RestClientException;
import org.springframework.web.client.RestTemplate;

import javax.validation.Valid;
import java.util.Map;

/**
 * <p>
 * Oauth控制类
 * </p>
 *
 * @Author: Haifeng
 * @date: 2020-08-17
 */
@Slf4j
@ApiSort(1)
@Api(tags = "Token管理")
@RestController
@RequestMapping("/oauth")
public class OauthController {

    @Value("${server.port}")
    private String port;

    public static final String NULLSTR = "null";

    /**
     * 登录获取Token
     * @param loginParam
     * @return
     */
    @ApiOperationSupport(order = 1)
    @ApiOperation(value = "登录获取Token", notes = "登录获取Token", produces = MimeTypeUtils.APPLICATION_JSON_VALUE)
    @PostMapping("/login")
    public Rest login(@Valid @RequestBody LoginParam loginParam, BindingResult result) {
        MultiValueMap<String, Object> paramsMap = new LinkedMultiValueMap<>();
        paramsMap.set("username", loginParam.getUsername());
        paramsMap.set("password", loginParam.getPassword());
        paramsMap.set("grant_type", loginParam.getGrantType());
        paramsMap.set("scope", loginParam.getScope());
        RestTemplate restTemplate = new RestTemplate();
        restTemplate.getInterceptors().add(new BasicAuthenticationInterceptor(loginParam.getClientId(), loginParam.getClientSecret()));
        OAuth2AccessToken token;
        try {
            token = restTemplate.postForObject("http://localhost:" + port + "/oauth/token", paramsMap, OAuth2AccessToken.class);
        } catch (RestClientException e) {
            throw new BusinessException(HttpStatus.HTTP_UNAUTHORIZED, "client参数错误");
        }
        if (ObjectUtil.isNull(token) || NULLSTR.equalsIgnoreCase(token.toString())){
            Map<String, Object> additionalInformation = token.getAdditionalInformation();
            Object data = additionalInformation.get("data");
            Integer code = Integer.parseInt(additionalInformation.get("code").toString());
            String message = (String) additionalInformation.get("message");
            return Rest.error(data, code, message);
        }
        return Rest.success(token);
    }

    /**
     * 刷新Token
     * @param refreshTokenParam
     * @return
     */
    @ApiOperationSupport(order = 2)
    @ApiOperation(value = "刷新Token", notes = "刷新Token", produces = MimeTypeUtils.APPLICATION_JSON_VALUE)
    @PostMapping("/refreshToken")
    public Rest refreshToken(@Valid @RequestBody RefreshTokenParam refreshTokenParam, BindingResult result) {
        MultiValueMap<String, Object> paramsMap = new LinkedMultiValueMap<>();
        paramsMap.set("refresh_token", refreshTokenParam.getRefreshToken());
        paramsMap.set("grant_type", refreshTokenParam.getGrantType());
        paramsMap.set("scope", refreshTokenParam.getScope());
        RestTemplate restTemplate = new RestTemplate();
        restTemplate.getInterceptors().add(new BasicAuthenticationInterceptor(refreshTokenParam.getClientId(), refreshTokenParam.getClientSecret()));
        OAuth2AccessToken token;
        try {
            token = restTemplate.postForObject("http://localhost:" + port + "/oauth/token", paramsMap, OAuth2AccessToken.class);
        } catch (RestClientException e) {
            throw new BusinessException(HttpStatus.HTTP_UNAUTHORIZED, "client参数错误");
        }
        if (ObjectUtil.isNull(token) || NULLSTR.equalsIgnoreCase(token.toString())){
            Map<String, Object> additionalInformation = token.getAdditionalInformation();
            Object data = additionalInformation.get("data");
            Integer code = Integer.parseInt(additionalInformation.get("code").toString());
            String message = (String) additionalInformation.get("message");
            return Rest.error(data, code, message);
        }
        return Rest.success(token);
    }
}
